#define _POSIX_SOURCE
#define _BSD_SOURCE

#include "dominion.h"
#include "dominion_helpers.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include "rngs.h"

#ifndef MAX_SUPP
#define MAX_SUPP 13
#endif

int checkGainCard(int expected, int supplyPos, struct gameState *post, int toFlag, int player)
{
	struct gameState pre;
	int result;

	/* Copy memory located at post to memory located at pre */
	memcpy(&pre, post, sizeof(struct gameState));

	result = gainCard(supplyPos, post, toFlag, player);
	assert(result == expected);
	
	if (result == 0) {

		// toFlag = 0 : add to discard
		// toFlag = 1 : add to deck
		// toFlag = 2 : add to hand
		if (toFlag == 1) {
			pre.deck[player][pre.deckCount[player]] = supplyPos;
			pre.deckCount[player]++;

		} else if (toFlag == 2) {
			pre.hand[player][pre.handCount[player]] = supplyPos;
			pre.handCount[player]++;
		
		} else {
			pre.discard[player][pre.discardCount[player]] = supplyPos;
			pre.discardCount[player]++;
		}
		pre.supplyCount[supplyPos]--;
	}

	assert(memcmp(&pre, post, sizeof(struct gameState)) == 0);

	return 0;
}

void sigabrt_catch(int sig)
{
	printf("SIGABRT has been caught\n");
	exit(0);
}

int main(int argc, char **argv)
{
	int i, n, expected, player, supplyPos, toFlag;

	int k[10] = {adventurer, council_room, feast, gardens, mine,
			remodel, smithy, village, baron, great_hall};

	struct gameState G;

	signal(SIGABRT, sigabrt_catch);

	printf("Testing gainCard.\n");

	printf("RANDOM TESTS.\n");

	/* Set Random Number Generator */
	SelectStream(2);
	PutSeed(3);

	for (n = 1; n <= 20000; n++) {
		for (i = 0; i < sizeof(struct gameState); i++) {
			((char *) &G)[i] = floor(Random() * 256);
		}
		player = floor(Random() * 4);
		supplyPos = k[(int) floor(Random() * 10)];
		toFlag = floor(Random() * 3);

		/* Randomly Set Game Numbers */ 
		G.deckCount[player] = floor(Random() * MAX_DECK);
		G.discardCount[player] = floor(Random() * MAX_DECK);
		G.handCount[player] = floor(Random() * MAX_HAND);
		for (i = 0; i < 10; i++) {
			G.supplyCount[k[i]] = floor(Random() * MAX_SUPP);
		}

		if (argc > 1 && strcmp(argv[1], "-v") == 0) {
			printf("Test #%5d: player = %d supplyPos = %2d toFlag = %d\n", n, player, supplyPos, toFlag);
		}
		
		if (G.supplyCount[supplyPos] == 0) {
			expected = -1;
		} else {
			expected = 0;
		}

		checkGainCard(expected, supplyPos, &G, toFlag, player);
	}

	printf ("ALL TESTS OK\n");

	return 0;
}